<?php
// +----------------------------------------------------------------------
// | IPHP
// +----------------------------------------------------------------------
// | This is an open source and simple PHP FrameWork.
// +----------------------------------------------------------------------
// | $Id$
// +----------------------------------------------------------------------

// 核心文件

namespace IPHP\Core;

if(!defined('IN_IPHP')) {
    exit('Access Denied'); 
}

class App {
    private static $_instance; 

    /**
     * 一些初始化的操作
     */
    protected function Init() {
        // 定义请求类型的常量
        define('TIME',      $_SERVER['REQUEST_TIME']);
        define('REQUEST_METHOD',$_SERVER['REQUEST_METHOD']);
        define('IS_GET',        REQUEST_METHOD =='GET' ? true : false);
        define('IS_POST',       REQUEST_METHOD =='POST' ? true : false);
        define('IS_AJAX',       (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') ? true : false);

        // 加载配置文件
        global $config;
        if(file_exists(CONF_PATH.'config.php')) require_once CONF_PATH.'config.php';

        // 创建系统配置常量        
        // 根据配置文件创建常量+++++++++++++++++++++++++++++++++
        
        if(isset($config['app_debug']) && $config['app_debug'])
            $config['app_debug'] ? error_reporting(E_ALL^E_NOTICE) : error_reporting(0);
        // 定义视图文件后缀名常量
        $config['template_suffix'] ? define('TEMPLATE_SUFFIX', $config['template_suffix']) : define('TEMPLATE_SUFFIX', '.html');

        // 定义运行环境及存储方式
        // TODO: 目前仅支持sae,或许还需要增加bae支持
        if(IS_SAE) {
            defined('STORAGE_TYPE')             || define('STORAGE_TYPE', 'Sae');
        } else {
            defined('STORAGE_TYPE')             || define('STORAGE_TYPE', 'Local');
        }

        //TODO: 暂时是写死默认的
        defined('DATA_PATH')             || define('DATA_PATH', __ROOT__.'/Data/'); 
        defined('STATIC_PATH')           || define('STATIC_PATH', DATA_PATH.'Static/'); 
        defined('UPLOAD_PATH')           || define('UPLOAD_PATH', DATA_PATH.'Upload/'); 
        // 根据配置文件创建常量 end ++++++++++++++++++++++++++++

    }

    // 执行应用
    public function Run() {
        // 设置自定义异常处理
        // register_shutdown_function('IPHP\Core\App::shutdownHandler');    
        set_error_handler('IPHP\Core\App::errorHandler', E_ALL);
        set_exception_handler('IPHP\Core\App::exceptionHandler');

        // 设置时间
        date_default_timezone_set(TIME_ZONE);
        // 注册自动加载
        spl_autoload_register('IPHP\Core\App::autoload');

        $this->Init();
        $this->exec();
    }

    /**
     * 执行操作
     * @return [type] [description]
     */
    protected function exec() {
        $router = new Router();
        $ret = $router->parseUrl();
        // 定义控制器目录
        defined('CONTROLLER_PATH')      || define('CONTROLLER_PATH', APP_PATH.MODULE_NAME.'/Controller/');
        // 定义视图模板目录
        defined('VIEW_PATH')            || define('VIEW_PATH', APP_PATH.MODULE_NAME.'/View/');
        // 定义模型目录
        defined('MODEL_PATH')           || define('MODEL_PATH', APP_PATH.MODULE_NAME.'/Model/');

        //　定义可在模板中使用的常量
        defined('__IMG__')              || define('__IMG__', STATIC_PATH.MODULE_NAME.'/images/');
        defined('__CSS__')              || define('__CSS__', STATIC_PATH.MODULE_NAME.'/css/'); 
        defined('__JS__')               || define('__JS__',  STATIC_PATH.MODULE_NAME.'/js/'); 
        defined('__STATIC__')           || define('__STATIC__',STATIC_PATH);
        defined('__PUBLIC__')           || define('__PUBLIC__',STATIC_PATH.'/Common/');


        // 执行操作
        $classfile = CONTROLLER_PATH.CONTROLLER_NAME.CLASS_EXT;

        if(file_exists($classfile)) {
            import(CONTROLLER_NAME, CONTROLLER_PATH, CLASS_EXT);
        } else {
            // 控制器文件不存在
            // 检查是否有空控制器，如果有则跳转过去，如果没有，则显示错误信息
            // TODO:
        }        

        $class = "App\Controller\\{$ret['controller']}";
        $controller = new $class();
        // 调用构造方法
        $controller->_init();

        // 检查操作是否存在
        if(method_exists($controller, $ret['action'])) {
            $controller->$ret['action']();
        } else {
            // 发果操作不存在，则继续检查空操作
            // TODO: 如果存在空操作，则跳转,否则显示错误信息
        }
    }


    static public function shutdownHandler() {
        $lasterror = error_get_last();
        if ($lasterror) {
            $error = strval(date('Y-m-d h:i:s')) . '=>' . '[SHUTDOWN] lvl:' . $lasterror['type'] . ' | msg:' . $lasterror['message'] . ' | file:' . $lasterror['file'] . ' | ln:' . $lasterror['line'] . "\r\n";

            if(STORAGE_TYPE == "Local") {
                $path = getLogPath();
                $logfile = $path.date('Ymd').'_shutdownlog.txt';
                file_put_contents($logfile, $error, FILE_APPEND);
            } else {

            }

            //提示用户
            ob_end_clean();
            exit("system Error!!");
        }
    }

    static public function errorHandler($errno, $errstr = '', $errfile = '', $errline = 0) { 
        $exception = new \ErrorException($errstr, 0, $errno, $errfile, $errline);
        $msg = strval(date('Y-m-d h:i:s')) . '=>' . 'Type:' . \IPHP\Core\App::getErrTypeName($errno) . "\r\n" . \IPHP\Core\App::getExecptionMsg($exception)."\r\n";


        $path = getLogPath();
        $logfile = $path.date('Ymd').'_error.txt';

        switch ($errno) {
            case E_NOTICE:
            case E_DEPRECATED:
                return;
        }
        throw $exception;
    }

    static public function getErrTypeName($errno) {
        switch ($errno) {
            case E_NOTICE:
                return 'E_NOTICE';
            case E_DEPRECATED:
                return 'E_DEPRECATED';
            default:
                return $errno;
        }
    }

    static public function exceptionHandler($ex) {
        $msg = strval(date('Y-m-d h:i:s')) . '=>' . \IPHP\Core\App::getExecptionMsg($ex)."\r\n";
        if(STORAGE_TYPE == "Local") {
            $path = getLogPath();
            $logfile = $path.date('Ymd').'_exception.txt';
            file_put_contents($logfile, $msg, FILE_APPEND);
        }
        include IPHP_PATH.'Tpl/exception.html';
    }

    static public function getExecptionMsg($exception) {
        //获取最准确的异常
        while ($exception->getPrevious()) {
            $exception = $exception->getPrevious();
        }
        $msg = ' Message: ' . $exception->getMessage();
        $msg .= ' File: ' . $exception->getFile() . ':' . $exception->getLine() . "\r\n";

        return $msg;
    }


    /**
     * 自动加载
     * @param  [type] $class [description]
     * @return [type]        [description]
     */
    public static function autoload($class) {
        // 框架命名空间
        import($class);
    }

    /**
     * 获取单例
     * @return [type] [description]
     */
    public static function getInstance() {    
        if(! (self::$_instance instanceof self) )   
        {    
            self::$_instance = new self();    
        }  
        return self::$_instance;       
    }

    private function __construct() {}
    private function __clone()  {}
}